package games.puzzle8;

import gps_api.Rule;
import gps_api.State;
import gps_exceptions.NotAppliableException;

public class Puzzle8Rule implements Rule{
	static final int MOV_UP=0;
	static final int MOV_RIGHT=1;
	static final int MOV_DOWN=2;
	static final int MOV_LEFT=3;
	
	private int [][]movVec={{0,-1}, {1,0}, {0,1}, {-1, 0}};
	private int typeMov;
	
	public Puzzle8Rule(int mov){
		if(mov>=MOV_UP && mov<=MOV_LEFT){
			typeMov= mov;
		}
	}
	
	@Override
	public State apply(State state) throws NotAppliableException {
		Puzzle8State newSate= new Puzzle8State();
		Puzzle8State state1= (Puzzle8State)state;
		int pos_x=0, pos_y=0;
		
		for(int y=0; y<Puzzle8State.SIZE_TABLE; y++){
			for(int x=0; x<Puzzle8State.SIZE_TABLE; x++){
				newSate.table[y][x]= state1.table[y][x];
				if(state1.table[y][x]==0){
					pos_x=x;
					pos_y=y;
				}
			}
		}
		
		try{
			newSate.table[pos_y][pos_x]= newSate.table[pos_y + movVec[typeMov][1]][pos_x + movVec[typeMov][0]];
			newSate.table[pos_y + movVec[typeMov][1]][pos_x + movVec[typeMov][0]]=0;
			newSate.setEmptyPos(pos_y + movVec[typeMov][1], pos_x + movVec[typeMov][0]);
		}catch (Exception e) {
			throw new NotAppliableException();
		}			
		
		return newSate;
	}

	@Override
	public Double getCost() {
		return 1.0;
	}
	
	@Override
	public String toString(){
		String ans;
		switch (typeMov) {
		case MOV_DOWN:
			ans= "Down";
			break;

		case MOV_LEFT:
			ans= "Left";
			break;
		case MOV_RIGHT:
			ans= "Right";
			break;
		case MOV_UP:
			ans= "Up";
			break;
		default:
			ans= "Nothing"; 
			break;
		}
		
		return ans;
	}

	@Override
	public boolean isApplicable(State state) {
		Puzzle8State state1= (Puzzle8State)state;
		int pos_x, pos_y;
		
		pos_y= state1.emptyPos/Puzzle8State.SIZE_TABLE;
		pos_x= state1.emptyPos - (pos_y*Puzzle8State.SIZE_TABLE);
		
		if((pos_x + movVec[typeMov][0])>= 0 &&
				(pos_x + movVec[typeMov][0])< Puzzle8State.SIZE_TABLE &&
				(pos_y + movVec[typeMov][1])>= 0 &&
				(pos_y + movVec[typeMov][1])< Puzzle8State.SIZE_TABLE ){
			return true;
		}else{
			return false;
		}
	}

}
